package com.baicaoyuan.web.service;

import com.baicaoyuan.web.common.StringUtils;
import com.baicaoyuan.web.common.excel.LotteryScoreInput;
import com.baicaoyuan.web.common.lottery.LotteryDomain;
import com.baicaoyuan.web.common.lottery.LotteryUtil;
import com.baicaoyuan.web.model.*;
import com.baicaoyuan.web.repository.*;
import com.baicaoyuan.web.request.br.*;
import com.baicaoyuan.web.response.*;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.transaction.Transactional;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class LotteryService {

    private final LotteryUtil lotteryUtil;

    private final LotteryProjectItemRepository lotteryProjectItemRepository;
    private final LotteryProjectRepository lotteryProjectRepository;
    private final LotteryScoreInputDetailRepository lotteryScoreInputDetailRepository;
    private final LotteryUserRepository lotteryUserRepository;
    private final JzzUserProjectRepository jzzUserProjectRepository;
    private final UserService userService;

    private final UserRepository userRepository;

    /**
     * excel 导入抽奖积分
     *
     * @param inputs
     * @param userId
     * @return
     */
    @Transactional
    public boolean saveLotteryScoreInput(List<LotteryScoreInput> inputs, Long userId) {
        if (CollectionUtils.isEmpty(inputs)) {
            return false;
        }
        UserDO user = userService.findOne(userId);
        List<LotteryScoreInputDetailDO> inputDetailDOS = Lists.newArrayListWithCapacity(inputs.size());

        inputs.forEach(i -> {
            JzzUserProjectDO jup = jzzUserProjectRepository.findBySerialNumber(i.getSno());
            if (jup != null) {
                LotteryScoreInputDetailDO inputDetailDO = new LotteryScoreInputDetailDO();
                inputDetailDO.setPeriodNo(i.getPeriodNo());
                inputDetailDO.setSerialNumber(i.getSno());
                inputDetailDO.setUserId(jup.getUserId());
                inputDetailDO.setScore(i.getScore());
                inputDetailDO.setUserName(user.getRealName());
                inputDetailDO.setOperator(userId);
                inputDetailDOS.add(inputDetailDO);
            }
        });
        boolean r = lotteryScoreInputDetailRepository.save(inputDetailDOS).size() > 0;
        if (r) {
            inputDetailDOS.forEach(x -> {
                boolean rr = userService.addOrReduceLotteryScore(x.getUserId(), x.getScore());
                if (!rr) {
                    throw new RuntimeException("积分导入失败！");
                }
            });
        }
        return r;
    }

    /**
     * 保存奖项设置
     *
     * @param request
     * @return
     */
    @Transactional
    public boolean saveLotteryProject(BAddLotteryProjectRequest request) {

        Integer i100 = request.getItems().stream().mapToInt(BAddLotteryProjectRequest.LotteryProjectItem::getV).sum();
        if (i100 != 1000) {
            throw new RuntimeException("请将几率总和设置为1000");
        }

        LotteryProjectDO lotteryProject = new LotteryProjectDO();
        lotteryProject.setOperator(request.getUserId());
        lotteryProject.setName(request.getName());
        lotteryProject.setThresholdScore(request.getThresholdScore());
        Long lotteryProjectId = lotteryProjectRepository.save(lotteryProject).getId();

        List<LotteryProjectItemDO> items = new ArrayList<>();
        request.getItems().forEach(x -> {
            LotteryProjectItemDO item = new LotteryProjectItemDO();
            item.setLotteryProjectId(lotteryProjectId);
            item.setCode(x.getCode());
            item.setContent(x.getContent());
            item.setPicture(x.getPicture());
            item.setV(x.getV());
            items.add(item);
        });
        return lotteryProjectItemRepository.save(items).size() > 0;
    }

    @Transactional
    public boolean updateLotteryProject(BAddLotteryProjectRequest request) {
        Integer i100 = request.getItems().stream().mapToInt(BAddLotteryProjectRequest.LotteryProjectItem::getV).sum();
        if (i100 != 1000) {
            throw new RuntimeException("请将几率总和设置为1000");
        }

        LotteryProjectDO lotteryProject = lotteryProjectRepository.getOne(request.getId());
        lotteryProject.setOperator(request.getUserId());
        lotteryProject.setName(request.getName());
        lotteryProject.setThresholdScore(request.getThresholdScore());

        lotteryProjectRepository.save(lotteryProject);
        lotteryProjectItemRepository.deleteByLotteryProjectIdFk(lotteryProject.getId());
        List<LotteryProjectItemDO> items = new ArrayList<>();
        request.getItems().forEach(x -> {
            LotteryProjectItemDO item = new LotteryProjectItemDO();
            item.setLotteryProjectId(lotteryProject.getId());
            item.setCode(x.getCode());
            item.setContent(x.getContent());
            item.setPicture(x.getPicture());
            item.setV(x.getV());
            items.add(item);
        });
        return lotteryProjectItemRepository.save(items).size() > 0;
    }

    /**
     * 获取奖项列表
     *
     * @return
     */
    public List<BLotteryProjectResponse> listLotteryProject() {
        List<BLotteryProjectResponse> result = new ArrayList<>();
        List<LotteryProjectDO> projects = lotteryProjectRepository.findAll();
        projects.forEach(p -> {
            BLotteryProjectResponse response = new BLotteryProjectResponse();
            BeanUtils.copyProperties(p, response);
            result.add(response);

            List<LotteryProjectItemDO> items = lotteryProjectItemRepository.findByLotteryProjectId(p.getId());
            List<BLotteryProjectResponse.LotteryProjectItem> itemsResponse = new ArrayList<>();
            items.forEach(i -> {
                BLotteryProjectResponse.LotteryProjectItem item = new BLotteryProjectResponse.LotteryProjectItem();
                BeanUtils.copyProperties(i, item);
                itemsResponse.add(item);
            });
            response.setItems(itemsResponse);
        });
        return result;
    }

    /**
     * 加载设置的奖项
     *
     * @return
     */
    private List<LotteryDomain> loadLotteryItems(Long id) {
        List<LotteryProjectItemDO> items = lotteryProjectItemRepository.findByLotteryProjectId(id);
        List<LotteryDomain> lotteryDomainList = new ArrayList<>();
        items.forEach(x -> {
            LotteryDomain domain = new LotteryDomain(x.getId(), x.getContent(), x.getV(), x.getPicture());
            lotteryDomainList.add(domain);

        });
        return lotteryDomainList;
    }

    /**
     * 获取奖项内容
     *
     * @return
     */
    public List<LotteryItemResponse> listLotteryItems(Long id) {
        List<LotteryItemResponse> result = new ArrayList<>();
        List<LotteryDomain> list = loadLotteryItems(id);
        for (LotteryDomain lotteryDomain : list) {
            LotteryItemResponse response = new LotteryItemResponse();
            BeanUtils.copyProperties(lotteryDomain, response);
            result.add(response);
        }
        return result;
    }


    /**
     * 抽奖
     *
     * @return
     */
    @Transactional
    public LotteryResultResponse generateAward(BLotteryDomainsGenerateRequest request) {
        LotteryProjectDO project = lotteryProjectRepository.getOne(request.getLotteryProjectId());
        UserDO user = userRepository.getOne(request.getUserId());
        if (user.getScore() < project.getThresholdScore()) {
            throw new RuntimeException("积分不够！");
        }

        List<LotteryDomain> list = loadLotteryItems(request.getLotteryProjectId());
        LotteryDomain lotteryDomain = lotteryUtil.generateAward(list);
        Long lotteryProjectItemId = lotteryDomain.getId();
        LotteryResultResponse response = new LotteryResultResponse();
        BeanUtils.copyProperties(lotteryDomain, response);
        saveLotteryUser(project, lotteryProjectItemId, user);
        return response;
    }


    private void saveLotteryUser(LotteryProjectDO project, Long lotteryProjectItemId, UserDO user) {
        LotteryProjectItemDO item = lotteryProjectItemRepository.getOne(lotteryProjectItemId);

        LotteryUserDO lu = new LotteryUserDO();
        lu.setUserId(user.getId());
        lu.setContent(item.getContent());
        lu.setCode(item.getCode());
        lu.setUserName(user.getRealName());
        lu.setScore(project.getThresholdScore());
        boolean s = lotteryUserRepository.save(lu) != null;
        if (s) {
            userService.addOrReduceLotteryScore(user.getId(), -project.getThresholdScore());
        }
    }


    /**
     * 获取个人中奖信息列表
     *
     * @param userId
     * @return
     */
    public List<LotteryUserResponse> getLotteryUserByUserId(Long userId) {
        List<LotteryUserDO> lotteryUserDOS = lotteryUserRepository.findByUserId(userId);
        List<LotteryUserResponse> result =
                lotteryUserDOS.stream().map(x -> {
                    LotteryUserResponse response = new LotteryUserResponse();
                    BeanUtils.copyProperties(x, response);
                    return response;
                }).collect(Collectors.toList());

        return result;
    }

    /**
     * 分页获取中奖信息列表
     *
     * @param request
     * @return
     */
    public List<LotteryUserExtResponse> getLotteryUserPage(BLotteryUserPageRequest request) {
        List<Object[]> list = lotteryUserRepository.getPage(StringUtils.plusPercent(request.getTelephone()), (request.getPage() - 1) * request.getSize() , request.getSize(), request.getStatus());
        List<LotteryUserExtResponse> result = new ArrayList<>();
        list.forEach(x -> {
            LotteryUserExtResponse response = new LotteryUserExtResponse();
            response.setId(Long.parseLong(x[0].toString()));
            response.setUserId(Long.parseLong(x[1].toString()));
            response.setUserName(x[2] == null ? "" : x[2].toString());
            response.setCode(x[3].toString());
            response.setContent(x[4].toString());
            response.setScore(Integer.parseInt(x[5].toString()));
            response.setStatus(Boolean.parseBoolean(x[6].toString()) ? 1 : 0);
            response.setCreateTime(Timestamp.valueOf(x[7].toString()));
            response.setLogistics(x[8] ==  null ? "": x[8].toString());
            response.setLogisticsNo(x[9] == null ? "" : x[9].toString());
            response.setTelephone(x[10].toString());
            response.setProvince(x[11] == null ? "" : x[11].toString());
            response.setCity(x[12] == null ? "" : x[12].toString());
            response.setArea(x[13] == null ? "" : x[13].toString());
            response.setAddress(x[14] == null ? "" : x[14].toString());
            result.add(response);
        });

        return result;
    }

    public Integer getCountOfAll(BLotteryUserPageRequest request) {
        return lotteryUserRepository.count(StringUtils.plusPercent(request.getTelephone()), request.getStatus());
    }


    public List<LotteryScoreInputDetailDO> getLotteryScorePage(BLotteryScorePageRequest request) {
        return lotteryScoreInputDetailRepository.getPage(StringUtils.plusPercent(request.getPeriodNo()), request.getPage(), request.getSize());
    }

    /**
     * 导入抽奖积分列表数
     *
     * @param request
     * @return
     */
    public Integer getLotteryScoreCountOfAll(BLotteryScorePageRequest request) {
        return lotteryScoreInputDetailRepository.count(StringUtils.plusPercent(request.getPeriodNo()));
    }

    public Boolean lotteryOver(BLotteryOverRequest request) {
        return request.getIds().stream().allMatch(x -> {
            LotteryUserDO userDO = lotteryUserRepository.findOne(x);
            userDO.setStatus(1);
            userDO.setLogistics(request.getLogistics());
            userDO.setLogisticsNo(request.getLogisticsNo());
            return lotteryUserRepository.save(userDO) != null;
        });
    }
}
